************************************************************************************
/*
Policy Feedback as Political Weapon: 
Conservative Advocacy and the Demobilization of the Public Sector Labor Movement

Forthcoming in Perspectives on Politics

Alexander Hertel-Fernandez
Columbia University
School of International and Public Affairs
ah3467@columbia.edu

Replication code for cross-state analysis of public union density and revenue

Originally run in Stata 15

*/
************************************************************************************

* Load cross-state data

use "crossstatedata.dta", clear

* Descriptive statistics

sum public_unionmem nearev_allwagesal policyinplace privatemem demvetopoints unemprate

/* Figure 1: The Evolution of Public Sector Labor Unions in the United States (right panel)

gen pubmem1996 = public_unionmem if year==1996
gen pubmem2016 = public_unionmem if year==2016

collapse (mean) pubmem1996 pubmem2016, by(statefip)

gen chng20161996 = pubmem2016-pubmem1996

histogram chng20161996, bin(50) frequency

*/

/* Figure 2: Conservative Cross-State Network Bill Passage and Public Union Strength

twoway (scatter public_unionmem_demeaned enacted_clock if enacted_clock>=-4 & enacted_clock<=4 & ever_e==1) (lowess public_unionmem_demeaned enacted_clock if enacted_clock>=-4 & enacted_clock<0 & ever_e==1)  (lowess public_unionmem_demeaned enacted_clock if enacted_clock>0 & enacted_clock<=4 & ever_e==1), xline(0, lcolor(black) lpattern(dash)) aspectratio(1) legend(off) graphregion(color(white)) xtitle("Years Before/After ALEC Bill Passage") ytitle("Public Sector Union Density" "(State Demeaned)") saving("publicdens_demeaned.gph", replace)
twoway (scatter nearev_allwagesal_demeaned enacted_clock if enacted_clock>=-4 & enacted_clock<=4 & ever_e==1) (lowess nearev_allwagesal_demeaned enacted_clock if enacted_clock>=-4 & enacted_clock<0 & ever_e==1)  (lowess nearev_allwagesal_demeaned enacted_clock if enacted_clock>0 & enacted_clock<=4 & ever_e==1), xline(0, lcolor(black) lpattern(dash)) aspectratio(1) legend(off) graphregion(color(white)) xtitle("Years Before/After ALEC Bill Passage") ytitle("NEA Affiliate Revenue/Worker" "(State Demeaned)") saving("nearev_demeaned.gph", replace)

*/

/* Appendix Figure 1: DID Plots

bys year: egen control_pubunionmem_tmp = mean(public_unionmem_demeaned) if ever_enacted == 0
bys year: egen control_pubunionmem = max(control_pubunionmem_tmp)
drop control_pubunionmem_tmp
sort statefip year
by statefip: gen treat_year_tmp = year if policyinplace[_n] == 1 & policyinplace[_n-1] == 0
by statefip: egen treat_year = max(treat_year_tmp)
drop treat_year_tmp
gen t = (year-treat_year)
gen treat_publicunionmem = public_unionmem_demeaned if ever_enacted == 1
gen obs = 1

bys year: egen control_nearev_tmp = mean(nearev_allwagesal_demeaned) if ever_enacted == 0
bys year: egen control_nearev = max(control_nearev_tmp)
drop control_nearev_tmp
sort statefip year
gen treat_nearev = nearev_allwagesal_demeaned if ever_enacted == 1

collapse (mean) treat_publicunionmem control_pubunionmem treat_nearev control_nearev (sum) obs, by(t)
keep if abs(t)<=3

twoway (line treat_publicunionmem t)  (line control_pubunionmem t), xline(0)  
twoway (line treat_nearev t)  (line control_nearev t), xline(0)

*/

* Main regression analysis reported in text (Tables 2 and 3)

quietly: xtreg public_unionmem policyinplace i.year, cluster(statefip) fe
estimates store m1
quietly: xtreg public_unionmem policyinplace privatemem demvetopoints unemprate i.year, cluster(statefip) fe
estimates store m2
quietly: xtreg public_unionmem L1.public_unionmem policyinplace privatemem unemprate demvetopoints i.year, cluster(statefip) fe
estimates store m3
quietly: xtreg public_unionmem policyinplace privatemem demvetopoints unemprate i.region##c.year i.year, cluster(statefip) fe
estimates store m4
quietly: reg public_unionmem policyinplace i.statefip if ever_e==1, cluster(statefip)
estimates store m5
quietly: reg public_unionmem policyinplace i.statefip if ever_e==1 & stateabb!="WI", cluster(statefip)
estimates store m6

quietly: xtreg nearev_allwagesal policyinplace i.year, cluster(statefip) fe
estimates store m10
quietly: xtreg nearev_allwagesal policyinplace privatemem demvetopoints unemprate i.year, cluster(statefip) fe
estimates store m11
quietly: xtreg nearev_allwagesal L1.nearev_allwagesal policyinplace privatemem demvetopoints unemprate i.year, cluster(statefip) fe
estimates store m12
quietly: xtreg nearev_allwagesal policyinplace privatemem demvetopoints unemprate i.region##c.year i.year, cluster(statefip) fe
estimates store m13
quietly: reg nearev_allwagesal policyinplace i.statefip if ever_e==1, cluster(statefip)
estimates store m14
quietly: reg nearev_allwagesal policyinplace i.statefip if ever_e==1 & stateabb!="WI", cluster(statefip)
estimates store m15

* Output main regressions in manuscript

estout m1 m2 m3 m4 m5 m6 using tab2_main.csv, cells(b(star fmt(2)) se(par fmt(2))) legend drop(_cons) stats(r2 N) starlevels(* 0.10 ** 0.05 *** 0.01) replace
estout m10 m11 m12 m13 m14 m15 using tab3_main.csv, cells(b(star fmt(2)) se(par fmt(2))) legend drop(_cons) stats(r2 N) starlevels(* 0.10 ** 0.05 *** 0.01) replace

* Appendix regressions - exclude ND & TN

quietly: reg public_unionmem policyinplace i.statefip if ever_e==1 & stateabb!="TN" & stateabb!="ND", cluster(statefip)
estimates store m1
quietly: reg nearev_allwagesal policyinplace i.statefip if ever_e==1 & stateabb!="TN" & stateabb!="ND", cluster(statefip)
estimates store m2

estout m1 m2 using append_tab1.csv, cells(b(star fmt(2)) se(par fmt(2))) legend drop(_cons) stats(r2 N) starlevels(* 0.10 ** 0.05 *** 0.01) replace

* Appendix regressions - jackknife and add biennium fixed effects

quietly jacknife _b: reg public_unionmem policyinplace i.statefip if ever_e==1
estimates store b1
quietly jacknife _b: reg public_unionmem policyinplace i.statefip i.twoyearnum if ever_e==1
estimates store b2
quietly jacknife _b: reg nearev_allwagesal policyinplace i.statefip if ever_e==1
estimates store b3
quietly jacknife _b: reg nearev_allwagesal policyinplace i.statefip i.twoyearnum if ever_e==1
estimates store b4

estout b1 b2 b3 b4 using append_tab2.csv, cells(b(star fmt(2)) se(par fmt(2))) legend drop(_cons) stats(r2 N) starlevels(* 0.10 ** 0.05 *** 0.01) replace

* Appendix regressions - control for DV four years before passage of ALEC legislation

quietly: reg public_unionmem public_unionmem4yearenacted policyinplace i.statefip if ever_e==1, cluster(statefip)
estimates store c1
quietly: reg nearev_allwagesal nearev_allwagesal4yearenacted policyinplace i.statefip if ever_e==1, cluster(statefip)
estimates store c2

estout c1 c2 using append_tab3.csv, cells(b(star fmt(2)) se(par fmt(2))) legend drop(_cons) stats(r2 N) starlevels(* 0.10 ** 0.05 *** 0.01) replace

* Appendix regressions - LDV with differenced outcome

quietly: xtreg D1.public_unionmem L1.public_unionmem policyinplace i.year, cluster(statefip) fe
estimates store d1

quietly: xtreg D1.nearev_allwagesal L1.nearev_allwagesal policyinplace i.year, cluster(statefip) fe
estimates store d2

estout d1 d2 using append_tab4.csv, cells(b(star fmt(2)) se(par fmt(2))) legend drop(_cons) stats(r2 N) starlevels(* 0.10 ** 0.05 *** 0.01) replace

* Appendix regressions - treated states with state-specific time trends

quietly: reg public_unionmem  policyinplace i.statefip##c.year if ever_e==1, cluster(statefip)
estimates store trend1

quietly: reg nearev_allwagesal policyinplace i.statefip##c.year if ever_e==1, cluster(statefip)
estimates store trend2

estout trend1 trend2 using append_tab5.csv, cells(b(star fmt(2)) se(par fmt(2))) legend drop(_cons) stats(r2 N) starlevels(* 0.10 ** 0.05 *** 0.01) replace

* Appendix regressions - logged NEA revenue instead of revenue/wage and salary workers

quietly: xtreg logrevenue policyinplace i.year, cluster(statefip) fe
estimates store m6
quietly: xtreg logrevenue policyinplace privatemem demvetopoints unemprate i.year, cluster(statefip) fe
estimates store m7
quietly: xtreg logrevenue L1.logrevenue policyinplace privatemem demvetopoints unemprate i.year, cluster(statefip) fe
estimates store m8
quietly: xtreg logrevenue policyinplace privatemem demvetopoints unemprate i.region##c.year i.year, cluster(statefip) fe
estimates store m9
quietly: reg logrevenue policyinplace i.statefip if ever_e==1, cluster(statefip)
estimates store m10
quietly: reg logrevenue policyinplace i.statefip if ever_e==1 & stateabb!="WI", cluster(statefip)
estimates store m11

estout m6 m7 m8 m9 m10 using append_tab6.csv, cells(b(star fmt(2)) se(par fmt(2))) legend drop(_cons) stats(r2 N) starlevels(* 0.10 ** 0.05 *** 0.01) replace

